package com.proton.carepatchtemp.service;

import android.app.Notification;
import android.app.PendingIntent;
import android.app.ProgressDialog;
import android.app.Service;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanResult;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.PowerManager;
import android.os.SystemClock;
import android.support.annotation.Nullable;
import android.support.annotation.RequiresApi;
import android.text.TextUtils;
import android.util.ArrayMap;

import com.apkfuns.logutils.LogUtils;
import com.proton.carepatchtemp.R;
import com.proton.carepatchtemp.activity.MainActivity;
import com.proton.carepatchtemp.application.VCare;
import com.proton.carepatchtemp.ble.BleManager;
import com.proton.carepatchtemp.constant.Codes;
import com.proton.carepatchtemp.constant.Settings;
import com.proton.carepatchtemp.constant.UUIDs;
import com.proton.carepatchtemp.database.Bean.BleWriteData;
import com.proton.carepatchtemp.database.TestManager;
import com.proton.carepatchtemp.database.daomanager.DeviceManager;
import com.proton.carepatchtemp.database.table.Device;
import com.proton.carepatchtemp.utils.AppUtils;
import com.proton.carepatchtemp.utils.TastyUtils;
import com.proton.carepatchtemp.utils.ThreadUtils;
import com.proton.carepatchtemp.utils.ble.BlueUtils;
import com.proton.carepatchtemp.utils.eventbus.MainEvent;
import com.proton.carepatchtemp.utils.net.DeviceCenter;
import com.sdsmdg.tastytoast.TastyToast;

import org.greenrobot.eventbus.EventBus;
import org.greenrobot.eventbus.Subscribe;

import java.lang.ref.WeakReference;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
import java.util.Queue;
import java.util.UUID;
import java.util.concurrent.ConcurrentLinkedQueue;

import static com.proton.carepatchtemp.constant.Settings.TEMP_LOAD_TIME_DIV;
import static com.proton.carepatchtemp.constant.UUIDs.CHARACTER_DATA_TEMP;
import static com.proton.carepatchtemp.constant.UUIDs.CHARACTER_HISTORY_TEMP;
import static com.proton.carepatchtemp.constant.UUIDs.CHARACTER_POWER_TEMP;
import static com.proton.carepatchtemp.constant.UUIDs.NTF_HISTORY_TEMP;
import static com.proton.carepatchtemp.constant.UUIDs.SERVER_DATA_TEMP;
import static com.proton.carepatchtemp.database.Bean.BleWriteData.CHAR_READ;


/**
 * Created by Fussen on 2016/11/7.
 * <p>
 * 蓝牙管理后台服务
 * 集中管理蓝牙设备
 * 与Activity采用跨进程通讯，增加保活概率防止被杀死
 */

public class BleService extends Service {
    public static final String TAG = "BleService";
    public static final int MSG_REGISTER = 1001;
    public static final int MSG_UNREGISTER = 1002;
    public static final int MSG_BLUETOOTH_OFF = 1003; // 手机蓝牙关闭
    public static final int MSG_BLUETOOTH_ON = 1004; // 手机蓝牙打开
    public static final int SCAN_BLE_DEVICE_RESULT = 1005; //搜索所有蓝牙设备后的结果
    public static final int MSG_OPEN_BLUETOOTH = 1006; //打开蓝牙
    public static final int MSG_START_SCAN = 1007; //开始搜索附近蓝牙设备
    public static final int MSG_SCAN_SUCCESS = 1008; //搜索到蓝牙设备
    public static final int MSG_SCAN_FAIL = 1009; //没有搜索到蓝牙设备
    public static final int CONNECT_BLE_DEVICE = 1010; //连接蓝牙设备
    public static final int MSG_DEVICE_CONNECT_STATE = 1011; //连接状态
    public static final int MSG_SEND_DATA_TIME_OUT = 1012; //发送数据超时
    public static final int MSG_BLE_WRITE_NAME_SUCCEED = 1013; //更改蓝牙设备名称成功
    public static final int MSG_CRC8_ERROR = 1014; //CRC8验证失败
    public static final int MSG_BLE_WRITE_NAME = 1015; //更改设备的名称
    public static final int MSG_NOT_FOUND_DEVICE_SERVICE = 1016; //没有发现设备服务
    public static final int MSG_SEND_DATA = 1017; // 发送蓝牙数据
    public static final int DISCONNECT_BLE_DEVICE = 1018; //断开连接
    public static final int MSG_ADD_DEVICE_CONNECT = 1019; //增加一个新的设备连接
    public static final int MSG_STOP_TEST = 1020; //断开一个设备连接
    public static final int MSG_DEVICE_POWER = 1021; //订阅设备电量通知
    public static final int MSG_DEVICE_CONNECT_FAILED = 1022;//设备连接失败
    //存放客户端的Messenger
    private final List<Messenger> mClients = new LinkedList<>();
    /**
     * 连接设备 如果GATT列表中对应的GATT对象不为空，则为重连
     */

    BluetoothGatt gatt = null;
    //    private Device tempDevice = null;
    //  连接的蓝牙设备相关信息
//    private List<Device> mLeDevices = new ArrayList<>(); // 扫描到所有蓝牙设备的集合
    private List<Integer> mDeviceAddress = new ArrayList<>(); // 扫描到所有设备的物理地址的hash集合 可以用来过滤掉重复的设备
    private List<String> disconnectMac = new ArrayList<>();
    private IncomingHandler mHandler;
    private Messenger mMessenger;
    private BluetoothAdapter mBlueToothAdapter;
    //
//    private BluetoothGatt tempBluetoothGatt;
    private BluetoothManager mBluetoothManager;
    private BluetoothDevice connecttingDevice;//需要连接的设备device
    private BluetoothGattService mDeviceService;//设备里的服务
    private BluetoothGattCharacteristic cmdRespondCharacter, cmdWriteCharacter, btWriteCharacter, btRespondCharacter;//设备服务里的Characteristic
    private ProgressDialog progressDialog;
    private PowerManager mPm;
    private PowerManager.WakeLock mWakelock;
    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private ScanCallback mScanCallback;
    /**
     * 扫描蓝牙后的回调
     */
    private BluetoothAdapter.LeScanCallback mLeScanCallback = (device, rssi, scanRecord) -> {
//        if ("BLE_TEMP".equalsIgnoreCase(device.getName()) && BlueUtils.getTypeScan(scanRecord) == 2) {
        LogUtils.d(device);
        LogUtils.d(BlueUtils.bytesToHexString(scanRecord));
        LogUtils.d(BlueUtils.parseData(scanRecord));
        LogUtils.d(scanRecord);

        if (device.getAddress().equalsIgnoreCase("0A:D0:AD:0A:D0:AD")) {
            Device dvc = new Device();
            dvc.setName(getString(R.string.tiwen) + device.getAddress().substring(12));
            dvc.setBtaddress(device.getAddress());
            if (!mDeviceAddress.contains(dvc.getBtaddress().hashCode())) {
                mDeviceAddress.add(dvc.getBtaddress().hashCode());
                EventBus.getDefault().post(new MainEvent(Codes.BT_SCAN_A_DVC, dvc));
            }

        }

        if ("BLE_TEMP".equalsIgnoreCase(device.getName())) {
            ThreadUtils.runOnOtherThread(() -> {
                Device dvc = new Device();
                dvc.setName(getString(R.string.tiwen) + device.getAddress().substring(12));
                dvc.setBtaddress(device.getAddress());
                //设备去重，已经测量的设备剔除

                if (!mDeviceAddress.contains(dvc.getBtaddress().hashCode()) && !TestManager.container.containsKey(dvc.getBtaddress())) {
                    if (DeviceManager.getMyDeviceByMac(dvc.getBtaddress()).size() > 0) {
                        EventBus.getDefault().post(new MainEvent(Codes.BT_SCAN_A_DVC, DeviceManager.getMyDeviceByMac(dvc.getBtaddress()).get(0)));
                        dvc = DeviceManager.getMyDeviceByMac(dvc.getBtaddress()).get(0);
                    } else {
                        EventBus.getDefault().post(new MainEvent(Codes.BT_SCAN_A_DVC, dvc));
                    }
                    mDeviceAddress.add(dvc.getBtaddress().hashCode());
                    LogUtils.d(dvc);
                } else {
                    //搜索不到设备
                    LogUtils.d(mDeviceAddress);
                    LogUtils.d(dvc.getBtaddress() + " address hash = " + dvc.getBtaddress().hashCode());
                    LogUtils.d(TestManager.container.keySet());
                }
            });
        }
    };
    /**
     * 蓝牙开关的监听器
     */
    protected BroadcastReceiver blueStateBroadcastReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {

            //通过intent获得蓝牙的状态
            int blueState = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, 0);
            switch (blueState) {
                case BluetoothAdapter.STATE_OFF://蓝牙关闭
                    //通知activity 蓝牙已关闭
                    TastyUtils.makeTextShort(R.string.string_ble_close, TastyToast.CONFUSING);

                    mHandler.post(() -> {
                        //应该在此处释放蓝牙
                        for (String mac :
                                getDeviceList().keySet()) {
                            disconnectDevice(mac);
                        }

                        //蓝牙初始化
                        BlueUtils.get();
                        mBluetoothManager = BlueUtils.get().getBluetoothManager();
                        mBlueToothAdapter = BlueUtils.get().getBlueToothAdapter();
                    });

                    break;
                case BluetoothAdapter.STATE_ON://蓝牙打开
                    //在这里要不要自动连接蓝牙  就看 你的了，这里暂时只是通知activity
                    //通知activity 蓝牙已打开
                    TastyUtils.makeTextShort(R.string.ble_opened, TastyToast.SUCCESS);
                    for (String mac :
                            TestManager.container.keySet()) {
                        ThreadUtils.runOnOtherThread(() -> {
                            String tempMac = mac;
                            connectDevice(mBlueToothAdapter.getRemoteDevice(tempMac));
                        });
                    }
                    break;
            }
        }
    };

    @Override
    public void onCreate() {
        super.onCreate();

        mPm = (PowerManager) getSystemService(Context.POWER_SERVICE);
        mWakelock = mPm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "mywakelock");
        mWakelock.acquire();

        LogUtils.d("1008611" + "=========服务第一次被创建===onCreate======");
        progressDialog = new ProgressDialog(BleService.this);
        EventBus.getDefault().register(BleService.this);
        //注册蓝牙开关状态的广播
        registerReceiver(blueStateBroadcastReceiver, new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED));

        //蓝牙初始化
        BlueUtils.get();
        mBluetoothManager = BlueUtils.get().getBluetoothManager();
        mBlueToothAdapter = BlueUtils.get().getBlueToothAdapter();

        //创建service中的Messenger 用来和activity通信
        mHandler = new IncomingHandler(this);
        mMessenger = new Messenger(mHandler);

        Notification.Builder builder = new Notification.Builder(BleService.this);

        builder.setContentText(getString(R.string.start_run));
        builder.setContentTitle(getString(R.string.running));
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setTicker(getString(R.string.care_patch_running));

        builder.setAutoCancel(false);
        builder.setWhen(System.currentTimeMillis());
        Intent intent = new Intent(VCare.get(), MainActivity.class);
        PendingIntent pendingIntent = PendingIntent.getActivity(BleService.this, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
        builder.setContentIntent(pendingIntent);
        Notification notification = builder.build();
        notification.flags = Notification.DEFAULT_LIGHTS;

        startForeground(1, notification);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        LogUtils.d("1008611" + "=========onStartCommand======");
        return START_STICKY;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        LogUtils.d("1008611" + "=========onBind======");
        return mMessenger.getBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        LogUtils.d("1008611" + "=========onUnbind======");
        for (String key :
                getDeviceList().keySet()) {
            disconnectDevice(key);
        }
        return super.onUnbind(intent);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        EventBus.getDefault().unregister(BleService.this);
        mWakelock.release();
        LogUtils.d("1008611" + "=========onDestroy======");
        //注销蓝牙监听广播
        unregisterReceiver(blueStateBroadcastReceiver);
    }

    public ArrayMap<String, BluetoothDevice> getDeviceList() {
        return BleManager.get().mBluetoothDeviceList;
    }

    public ArrayMap<String, BluetoothGatt> getGattlist() {
        return BleManager.get().mBluetoothGattList;
    }

    @Subscribe
    public void dealOnEvent(MainEvent event) {
        if (canDeal(event)) {
            try {
                dealEvent(event);
            } catch (Throwable e) {
                LogUtils.e(e);
            }
        }
    }

    public boolean canDeal(MainEvent event) {
        return event != null;
    }

    public void dealEvent(MainEvent event) {
        switch (event.getId()) {
            //开始扫描设备
            case Codes.BT_START_SEARCH_DEVICE:
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                    LogUtils.d("Receive Start Scan! startScanBleDeviceLOLLIPOP ");
                    startScanBleDeviceLOLLIPOP();
                } else {
                    startScanBleDevice();
                }
                break;
            //连接设备
            case Codes.BT_CONNECT_DEVICE:
                if (mBlueToothAdapter == null) {
                    mBlueToothAdapter = mBluetoothManager.getAdapter();
                }
                Device tempDevice = (Device) event.getObj();//拿到activity传过来的设备信息

                //通过mac地址连接设备
                BluetoothDevice bluetoothDevice = mBlueToothAdapter.getRemoteDevice(tempDevice.getBtaddress());

                connectDevice(bluetoothDevice);

                break;
            //重新连接
            case Codes.BT_RECONNECT_DEVICE:
                if (mBlueToothAdapter == null) {
                    mBlueToothAdapter = mBluetoothManager.getAdapter();
                }
                tempDevice = (Device) event.getObj();//拿到activity传过来的设备信息

                //通过mac地址连接设备
                BluetoothDevice bluetoothDevice1 = mBlueToothAdapter.getRemoteDevice(tempDevice.getBtaddress());

                connectDevice(bluetoothDevice1);
                break;

            //十分钟内自动重连
            case Codes.BT_RECONNECT:
                if (mBlueToothAdapter == null) {
                    mBlueToothAdapter = mBluetoothManager.getAdapter();
                }
                tempDevice = (Device) event.getObj();//拿到activity传过来的设备信息
                BluetoothDevice bluetoothDevice2 = mBlueToothAdapter.getRemoteDevice(tempDevice.getBtaddress());

                reconnectDevice(bluetoothDevice2);

                break;
            //停止测量
            case Codes.BT_STOP_TEST:
                LogUtils.e(event.getKey());
                disconnectDevice(event.getKey());
                break;
            default:
                break;
        }
    }

    /**
     * 更改设备名称的指令
     */
    private void btWriteCmd(BluetoothGatt gatt, String values) {

        //各个厂家的指令都不一样，只是举个例子 这里将values转化了下 然后写出去 具体转化格式 根据厂家来定

        byte[] cmdByte1 = "NAM".getBytes();
        byte[] cmdByte2 = values.getBytes();
        byte[] cmdByte = new byte[cmdByte1.length + cmdByte2.length + 1];

        System.arraycopy(cmdByte1, 0, cmdByte, 0, cmdByte1.length);
        cmdByte[cmdByte1.length] = (byte) cmdByte2.length;
        System.arraycopy(cmdByte2, 0, cmdByte, cmdByte1.length + 1, cmdByte2.length);

        if (btWriteCharacter != null && gatt != null) {

            //将指令放置进特征中
            btWriteCharacter.setValue(cmdByte);
            //设置回复形式WRITE_TYPE_NO_RESPONSE 这样速度会快
            btWriteCharacter.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_NO_RESPONSE);
            //写出去
            gatt.writeCharacteristic(btWriteCharacter);
        }
    }

    private void connectDevice(BluetoothDevice device) {

        if (device == null) {
            EventBus.getDefault().post(new MainEvent(Codes.BT_CONNECT_FAILED));
            return;
        }

        connecttingDevice = device;

        disconnectMac.clear();
        Device dvc = new Device();
        dvc.setName(getString(R.string.tiwen) + device.getAddress().substring(12));
        dvc.setBtaddress(device.getAddress());
        if (null != getGattlist().get(device.getAddress())) {
            getGattlist().get(device.getAddress()).connect();
            ThreadUtils.runOnOtherThread(() -> {
                LogUtils.d(" mBluetoothGattList contain connectDevice ! ");
                SystemClock.sleep(10 * 1000);
                LogUtils.d("contain BT_CONNECT_FAILED prepare send !");

                if (mBluetoothManager.getConnectionState(device, BluetoothProfile.GATT) != BluetoothProfile.STATE_CONNECTED) {
                    EventBus.getDefault().post(new MainEvent(device.getAddress(), Codes.BT_CONNECT_FAILED));
//                    LogUtils.d("contain BT_CONNECT_FAILED send !");
//                    mBluetoothGattList.get(device.getAddress()).close();
//                    disconnectDevice(device.getAddress());
                }
            });
        } else {
            //开启异步连接任务
            ThreadUtils.runOnOtherThread(() -> {

                if (mBlueToothAdapter != null) {
                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                        mBlueToothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
                    } else {
                        mBlueToothAdapter.stopLeScan(mLeScanCallback);
                    }
                }
                LogUtils.d(" mBluetoothGattList have not connectDevice! ");

                try {
                    gatt = device.connectGatt(BleService.this, false, new MyGattCallback(dvc));
                } catch (Exception e) {
                    LogUtils.e(e);
                }
            });

            ThreadUtils.runOnOtherThread(() -> {
                SystemClock.sleep(10 * 1000);
                LogUtils.d(getDeviceList());
                LogUtils.d(disconnectMac);
                if (!getDeviceList().containsKey(device.getAddress()) && !disconnectMac.contains(device.getAddress())) {
                    LogUtils.d(" connect device failed!  BT_CONNECT_FAILED");
                    EventBus.getDefault().post(new MainEvent(device.getAddress(), Codes.BT_CONNECT_FAILED));
                    if (gatt != null) {
                        gatt.close();
                        gatt = null;
                        disconnectDevice(device.getAddress());
                    }
                }
//                LogUtils.d(mBluetoothDeviceList);
//                LogUtils.d(disconnectMac);
            });
        }
    }

    private void reconnectDevice(BluetoothDevice device) {

        if (device == null) {
            return;
        }

        connecttingDevice = device;

        disconnectMac.clear();
        Device dvc = new Device();
        dvc.setName(getString(R.string.tiwen) + device.getAddress().substring(12));
        dvc.setBtaddress(device.getAddress());
        if (null != getGattlist().get(device.getAddress())) {
            getGattlist().get(device.getAddress()).connect();
        } else {
            //开启异步连接任务
            ThreadUtils.runOnOtherThread(() -> {
                LogUtils.d(" mBluetoothGattList have not connectDevice! ");

                try {
                    gatt = device.connectGatt(BleService.this, false, new MyGattCallback(dvc));
                } catch (Exception e) {
                    LogUtils.e(e);
                }
            });
        }
    }

    /**
     * 断开设备
     *
     * @param mac 通过mac地址获取要断开连接的蓝牙设备
     */
    private void disconnectDevice(String mac) {
        try {
            //防止错误提示设备连接失败
            disconnectMac.add(mac);
//        BluetoothDevice disconnectDevice = mBluetoothDeviceList.get(mac);
            BluetoothGatt disconnectGatt = getGattlist().get(mac);
            if (null != disconnectGatt) {
                disconnectGatt.close();
                disconnectGatt = null;
                getDeviceList().remove(mac);
                getGattlist().remove(mac);
                EventBus.getDefault().post(new MainEvent(mac, Codes.BT_DISCONNECT_DEVICE));
            } else {
                getDeviceList().remove(mac);
                getGattlist().remove(mac);
                EventBus.getDefault().post(new MainEvent(mac, Codes.BT_DISCONNECT_DEVICE));
            }
            getDeviceList().remove(mac);
            getGattlist().remove(mac);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 解析蓝牙设备返回的数据
     */
    private void handleBTDataAvailable(byte[] data) {

        //在这里我只 我们只看操作设备名称是否成功 不做其他操作
        if (data.length == 2) {
            if (data[0] == 79 && data[1] == 75) {   // 改设备名的返回(OK)
                Message msg = Message.obtain(null, MSG_BLE_WRITE_NAME_SUCCEED);
                msg.obj = data;
                sendMessage(msg);
            }
        } else {
            //更改失败 暂不做处理
        }
    }

    /**
     * 发送超时信息
     */
    private void sendTimeOutMessage() {
        Message message = Message.obtain(null, MSG_SEND_DATA_TIME_OUT);
        sendMessage(message);
    }

    private void sendDeviceConnectionState(String mac, int state) {
        Message msg = new Message();
        msg.what = state;
        msg.obj = mac;
        sendMessage(msg);
    }

    /**
     * 服务开始扫描所有蓝牙设备
     */
    private void startScanBleDevice() {
        if (mBlueToothAdapter.getState() == BluetoothAdapter.STATE_OFF) {
            mBlueToothAdapter.enable();
        }
        mHandler.postDelayed(() -> {
            mBlueToothAdapter.stopLeScan(mLeScanCallback); // 20秒后结束扫描
            // 通知界面扫描结束 并传递数据
            if (mDeviceAddress != null && mDeviceAddress.size() > 0) {
                //将扫描到的蓝牙设备集合传递到activity去

            } else {
                // 通知没有扫描到
                TastyUtils.makeTextShort(R.string.have_no_device, TastyToast.ERROR);
            }
        }, Settings.SEARCH_TIME);

        mDeviceAddress.clear();
        mBlueToothAdapter.startLeScan(mLeScanCallback);
    }

    @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
    private void startScanBleDeviceLOLLIPOP() {

        //设备去重，已经测量的设备不剔除
//搜索不到设备
        mScanCallback = new ScanCallback() {
            @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
            @Override
            public void onScanResult(int callbackType, ScanResult result) {
                LogUtils.d(result);
                LogUtils.d(BlueUtils.bytesToHexString(result.getScanRecord().getBytes()));
                LogUtils.d(BlueUtils.parseData(result.getScanRecord().getBytes()));

                if (result.getDevice().getAddress().equalsIgnoreCase("0A:D0:AD:0A:D0:AD")) {
                    Device dvc = new Device();
                    dvc.setName(getString(R.string.tiwen) + result.getDevice().getAddress().substring(12));
                    dvc.setBtaddress(result.getDevice().getAddress());
                    if (!mDeviceAddress.contains(dvc.getBtaddress().hashCode())) {
                        mDeviceAddress.add(dvc.getBtaddress().hashCode());
                        EventBus.getDefault().post(new MainEvent(Codes.BT_SCAN_A_DVC, dvc));
                    }
                }

                if ("BLE_TEMP".equalsIgnoreCase(result.getDevice().getName())) {
                    ThreadUtils.runOnOtherThread(() -> {
                        Device dvc = new Device();
                        dvc.setName(getString(R.string.tiwen) + result.getDevice().getAddress().substring(12));
                        dvc.setBtaddress(result.getDevice().getAddress());
                        //设备去重，已经测量的设备不剔除
                        if (!mDeviceAddress.contains(dvc.getBtaddress().hashCode()) && !TestManager.container.containsKey(dvc.getBtaddress())) {
                            EventBus.getDefault().post(new MainEvent(Codes.BT_SCAN_A_DVC, dvc));
                            mDeviceAddress.add(dvc.getBtaddress().hashCode());
                            LogUtils.d(dvc);
                        } else {
                            //搜索不到设备
                            LogUtils.d(mDeviceAddress);
                            LogUtils.d(dvc.getBtaddress() + " address hash = " + dvc.getBtaddress().hashCode());
                            LogUtils.d(TestManager.container.keySet());
                        }
                    });
                }

            }

            @Override
            public void onBatchScanResults(List<ScanResult> results) {
                super.onBatchScanResults(results);
            }

            @Override
            public void onScanFailed(int errorCode) {
                super.onScanFailed(errorCode);
            }
        };

        mHandler.postDelayed(() -> {
//            mBlueToothAdapter.stopLeScan(mLeScanCallback); // 20秒后结束扫描
            if (null != mBlueToothAdapter.getBluetoothLeScanner()) {
                mBlueToothAdapter.getBluetoothLeScanner().stopScan(mScanCallback);
            } else {
                TastyUtils.makeTextShort(R.string.string_ble_close, TastyToast.WARNING);
            }

            // 通知界面扫描结束 并传递数据
            if (mDeviceAddress != null && mDeviceAddress.size() > 0) {
                //将扫描到的蓝牙设备集合传递到activity去

            } else {
                // 通知没有扫描到
                TastyUtils.makeTextShort(R.string.have_no_device, TastyToast.ERROR);
            }
        }, Settings.SEARCH_TIME);
        mDeviceAddress.clear();
        mBlueToothAdapter.getBluetoothLeScanner().startScan(mScanCallback);
    }

    /**
     * 扫描蓝牙设备的结果
     */
    protected void scanBleResult(int result, ArrayList<BluetoothDevice> list) {
    }

    /**
     * 可以向所有绑定服务的activity发送消息
     *
     * @param msg 消息主体
     */
    private void sendMessage(Message msg) {
        for (int i = mClients.size() - 1; i >= 0; i--) {
            Message message = new Message();
            message.what = msg.what;
            message.arg1 = msg.arg1;
            message.arg2 = msg.arg2;
            message.obj = msg.obj;
            Messenger messenger = mClients.get(i);
            if (null != msg.obj) {
                LogUtils.d(msg.obj);
            }
            sendMessage(messenger, message);
        }
    }

    /**
     * 发送消息
     */
    private boolean sendMessage(Messenger messenger, Message msg) {
        boolean success = true;
        try {
            LogUtils.d(msg.what);
            LogUtils.d(msg.obj);
            messenger.send(msg);
        } catch (Exception e) {
            LogUtils.d(TAG + " Lost connection to client" + e);
            success = false;
        }
        return success;
    }

    // service 端 Handler 的实现
    private static class IncomingHandler extends Handler {
        private final WeakReference<BleService> mService;

        //使用弱引用进行优化
        public IncomingHandler(BleService service) {
            mService = new WeakReference<>(service);
        }

        //用来处理activity发来的消息
        @Override
        public synchronized void handleMessage(Message msg) {

            //拿到service对象
            BleService service = mService.get();
            if (service != null) {
                switch (msg.what) {
                    case MSG_REGISTER:
                        service.mClients.add(msg.replyTo);//添加订阅者
                        LogUtils.d("======注册service=====");
                        break;

                    case MSG_UNREGISTER:
                        service.mClients.remove(msg.replyTo);//移除此消息
                        LogUtils.d("======注销service=====");
                        break;
                    case MSG_STOP_TEST:
                        service.disconnectDevice(msg.obj.toString());
                        break;
                    default:
                        super.handleMessage(msg);

                }
            }
        }
    }

    /**
     * 蓝牙连接回调
     */
    private class MyGattCallback extends BluetoothGattCallback {


        //数据队列
        private final Queue<BleWriteData> mWriteQueue = new ConcurrentLinkedQueue<>();
        ArrayMap<String, List<Float>> dataKV = new ArrayMap<>();
        private boolean isWriting = false;//正在写入数据
        private BleWriteData latSendData;
        private BleWriteData reSendData;//重新发送的数据
        private int timeOutNum = 0;//超时次数
        private boolean timeOutThread_Start = false;//超时线程是否开始
        private int timeOutTime = 0; //超时时间标记
        private Device mDevice;
        private String mac;
        //  第一次连接读取缓存标志位 V1.0.2
//        private boolean isFirst = true;
        //  缓存读取标志位
        private boolean isReadCache = false;
        //  缓存数据长度
        private int cacheLength = 0;
        //  缓存数据
        private List<Float> cacheData = new ArrayList<>();
        //  电量订阅成功标志位
        private boolean isNtfPower = false;
        //  历史数据通知订阅标志位
        private boolean isNtfHistory = false;
        //  对应的Gatt对象，需要及时更新，避免缓存
        private BluetoothGatt mGatt;
        //  实时温度char
        private BluetoothGattCharacteristic mDataChar;
        //  电量ntf
        private BluetoothGattCharacteristic mPowerNTF;
        //  缓存数据ntf
        private BluetoothGattCharacteristic mHistoryTempNTF;
        //  缓存数据char
        private BluetoothGattCharacteristic mHistoryTempChar;
        private BluetoothGattService mDataService;
        //设备信息相关的server
        private BluetoothGattService mDeviceInfoServer;
        //  设备SN特征值
        private BluetoothGattCharacteristic mSNChar;
        //  固件版本号
        private BluetoothGattCharacteristic firmwareVersion;
        //超时线程
        private TimeOutThread timeOutThread;
        //连接状态标志位
        private boolean isConnected = false;

        public MyGattCallback(Device device) {
            if (null != device) {
                this.mDevice = device;
                mac = device.getBtaddress();
            }
        }

        private void initData() {

            isWriting = false;//正在写入数据

            latSendData = null;
            BleWriteData reSendData;//重新发送的数据

            timeOutNum = 0;//超时次数

            timeOutThread_Start = false;//超时线程是否开始

            timeOutTime = 0; //超时时间标记

            isReadCache = false;

            isWriting = false;

            mWriteQueue.clear();

            isNtfPower = false;

            isNtfHistory = false;
        }

        //连接状态回调方法
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            mGatt = gatt;
            //从数据库获取设备信息
            if (null != DeviceManager.getMyDeviceByMac(gatt.getDevice().getAddress()) && 0 < DeviceManager.getMyDeviceByMac(gatt.getDevice().getAddress()).size()) {
                mDevice = DeviceManager.getMyDeviceByMac(gatt.getDevice().getAddress()).get(0);
                LogUtils.d(mDevice);
            }
            LogUtils.d(mDevice);

            if (BluetoothProfile.STATE_CONNECTING == newState) {
                EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.DEVICE_STATE_CONNECTING));
            }

            if (BluetoothProfile.STATE_CONNECTED == newState) {

                isConnected = true;

                getGattlist().put(mDevice.getBtaddress(), gatt);
                EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.DEVICE_STATE_CONNECTED));
                LogUtils.d("=======设备连接连接成功======");
                //去发现该设备服务
                gatt.discoverServices();

            } else if (BluetoothProfile.STATE_DISCONNECTED == newState) {
                //断开连接
                isConnected = false;

                //断开后实时数据设置为null
                if (TestManager.get(mDevice.getBtaddress()) != null) {
                    TestManager.get(mDevice.getBtaddress()).realTemp = null;
                }

                initData();
                EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.DEVICE_STATE_DISCONNECTED));
                if (null != gatt) {
                    gatt.connect();
                } else {

                }
                LogUtils.d("=======设备断开连接=======");
            }
        }

        @Override
        public void onServicesDiscovered(final BluetoothGatt gatt, int status) {
            mGatt = gatt;
            if (status == BluetoothGatt.GATT_SUCCESS) {//已发现该设备的服务

                //寻找服务之后，我们就可以和设备进行通信，比如下发配置值，获取设备电量什么的
                LogUtils.d("=======onServicesDiscovered======");
                //发现该设备的服务
                //拿到该服务 1,通过UUID拿到指定的服务  2,可以拿到该设备上所有服务的集合
                //测量数据相关的server
                mDataService = gatt.getService(java.util.UUID.fromString(SERVER_DATA_TEMP));
                LogUtils.d("=======findMyService======");
                //设备信息相关的server
                mDeviceInfoServer = gatt.getService(UUID.fromString(UUIDs.SERVER_DEVICE_INFO));

                //  实时温度char
                mDataChar = mDataService.getCharacteristic(java.util.UUID.fromString(CHARACTER_DATA_TEMP));
                //  电量ntf
                mPowerNTF = mDataService.getCharacteristic(java.util.UUID.fromString(CHARACTER_POWER_TEMP));
                //  缓存数据ntf
                mHistoryTempNTF = mDataService.getCharacteristic(java.util.UUID.fromString(NTF_HISTORY_TEMP));
                //  缓存数据char
                mHistoryTempChar = mDataService.getCharacteristic(java.util.UUID.fromString(CHARACTER_HISTORY_TEMP));
                //  获取sn
                if (null != mDeviceInfoServer) {
                    LogUtils.d("Find Device SN Char !");
                    mSNChar = mDeviceInfoServer.getCharacteristic(UUID.fromString(UUIDs.CHARACTER_SN));
                    firmwareVersion = mDeviceInfoServer.getCharacteristic(UUID.fromString(UUIDs.FIRMWARE_VERSION));
                }
                //  相关服务判空
                if (null != mDataService &&
                        null != mDeviceInfoServer &&
                        null != mDataChar &&
                        null != mPowerNTF &&
                        null != mHistoryTempNTF &&
                        null != mSNChar &&
                        null != firmwareVersion) {

                    ThreadUtils.runOnOtherThread(() -> {
                        //  发现数据服务通知
                        Message message = new Message();
                        message.what = BleService.MSG_ADD_DEVICE_CONNECT;
                        message.obj = mDevice;
                        sendMessage(message);

                        SystemClock.sleep(200);

                        if (!TextUtils.isEmpty(mDevice.getVersion())) {
                            getDeviceList().put(gatt.getDevice().getAddress(), gatt.getDevice());
                            getGattlist().put(gatt.getDevice().getAddress(), gatt);
                            enableNotification(true, gatt, mHistoryTempNTF);
                            enableNotification(true, gatt, mPowerNTF);
                            nextWrite();
                        } else {
                            //获取设备版本号
                            obtainFirmWareVersion();
                        }
                    });

                } else {
                    //未发现该设备的服务
                    Message message = new Message();
                    message.what = MSG_NOT_FOUND_DEVICE_SERVICE;
                    sendMessage(message);
                    disconnectDevice(gatt.getDevice().getAddress());
                }

            } else {
                //未发现该设备的服务
                Message message = new Message();
                message.what = MSG_NOT_FOUND_DEVICE_SERVICE;
                sendMessage(message);
                disconnectDevice(gatt.getDevice().getAddress());
            }
        }

        /**
         * 当你调用了readCharacteristic()方法后
         * 此方法会执行，在这里返回你想要的Characteristic数据
         * 也就是说 你是主动的获取Characteristic值，而不是等着设备给你返回
         */
        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            mGatt = gatt;
            if (!getGattlist().containsKey(mDevice.getBtaddress())) {
                disconnectDevice(mDevice.getBtaddress());
                gatt.close();
                isWriting = false;
                mWriteQueue.clear();
                return;
            }

            if (status == BluetoothGatt.GATT_SUCCESS) {
                switch (characteristic.getUuid().toString().trim()) {
                    //设备固件版本号
                    case UUIDs.FIRMWARE_VERSION:
                        LogUtils.d("=====BLE===== Read device firmware version " + new String(characteristic.getValue()));
                        mDevice.setVersion(new String(characteristic.getValue()));
                        if (TextUtils.isEmpty(mDevice.getVersion())) {
                            obtainFirmWareVersion();
                        } else {
                            if (TextUtils.isEmpty(mDevice.getSn())) {
                                obtainDeviceSn();
                            } else {
                                TestManager.setDevice(mDevice.getBtaddress(), mDevice);
                                enableNotification(true, gatt, mPowerNTF);
                                enableNotification(true, gatt, mHistoryTempNTF);
                                nextWrite();
                            }
                        }
                        break;
                    //SN
                    case UUIDs.CHARACTER_SN:
                        LogUtils.d("=====Ble===== Read Device SN  " + new String(characteristic.getValue()));
                        mDevice.setSn(new String(characteristic.getValue()));
                        if (TextUtils.isEmpty(mDevice.getSn())) {
                            obtainDeviceSn();
                        } else {
                            TestManager.setDevice(mDevice.getBtaddress(), mDevice);
                            enableNotification(true, gatt, mPowerNTF);
                            enableNotification(true, gatt, mHistoryTempNTF);
                            nextWrite();
                            DeviceCenter.add(mDevice);
                        }
                        LogUtils.d(mDevice);
                        break;
                    case CHARACTER_DATA_TEMP:
                        //  添加至集合
                        getDeviceList().put(mDevice.getBtaddress(), mBlueToothAdapter.getRemoteDevice(mDevice.getBtaddress()));
                        getGattlist().put(mDevice.getBtaddress(), gatt);

                        float a = Integer.parseInt(BlueUtils.bytesToHexStringChange(characteristic.getValue()), 16);
                        float b = a / 100;
                        if (TestManager.get(mDevice.getBtaddress()) != null) {
                            TestManager.get(mDevice.getBtaddress()).setRealTemp(b);
                        }

                        LogUtils.d("==========Read CHAR_DATA_TEMP ============ " + b);
                        ThreadUtils.runOnOtherThread(() -> {
                            SystemClock.sleep(TEMP_LOAD_TIME_DIV);
                            if (!getGattlist().containsKey(mDevice.getBtaddress())) {
                                disconnectDevice(mDevice.getBtaddress());
                                gatt.close();
                            }
                            if (isConnected && !isReadCache) {
                                obtainRealTemp();
                                obtainDevicePower();
                            }
                        });
                        break;
                    case UUIDs.CHARACTER_POWER_TEMP:
                        //可读可订阅电量 //一分钟发送一次
                        int power = Integer.parseInt(BlueUtils.bytesToHexString(characteristic.getValue()), 16);
//                        LogUtils.d("Read Power CHAR power = " + power);
                        EventBus.getDefault().post(new MainEvent(gatt.getDevice().getAddress(), Codes.BT_DEVICE_POWER_VALUE, power));
                        break;
                    default:
                        break;
                }
            }

            if (mWriteQueue.isEmpty()) {
                isWriting = false;
                //可以在此处通知页面或者做其他工作
            } else {
                //如果队列中还有数据，继续写入
                isWriting = false;
                nextWrite();
            }

        }

        /**
         * 被订阅的Characteristic的值要是改变 调用此方法
         * 执行此方法的前提就是要被订阅
         */
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            mGatt = gatt;
            //发送电量通知
            if (characteristic.getUuid().toString().trim().equalsIgnoreCase(CHARACTER_POWER_TEMP)) {
                // 电量通知订阅成功
                int power = Integer.parseInt(BlueUtils.bytesToHexString(characteristic.getValue()), 16);
                EventBus.getDefault().post(new MainEvent(gatt.getDevice().getAddress(), Codes.BT_DEVICE_POWER_VALUE, power));
            }

            //缓存
            if (characteristic.getUuid().toString().trim().equalsIgnoreCase(NTF_HISTORY_TEMP)) {
                if (!isReadCache) {
                    String countString = BlueUtils.bytesToHexString(characteristic.getValue()).substring(0, 4);
                    int count = Integer.parseInt(countString.substring(2, 4) + countString.substring(0, 2), 16);

                    //开始测量时间
                    if (null == TestManager.getStartTime(mDevice.getBtaddress())) {
                        if (AppUtils.compareVersion(mDevice.getVersion(), "1.0.2") < 0) {
                            TestManager.setStartTime(mDevice.getBtaddress(), System.currentTimeMillis() - count * 4 * 10 * 1000);
                        } else {
                            TestManager.setStartTime(mDevice.getBtaddress(), System.currentTimeMillis() - count * 24 * 1000);
                        }
                        EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.DEVICE_FIRST_CONNECT));
                    }
                    LogUtils.e("History data number :" + count);
                    //
                    if (0 < count) {
                        cacheData.clear();
                        cacheLength = count;
                        isReadCache = true;

                        if (AppUtils.compareVersion(mDevice.getVersion(), "1.0.2") < 0) {

                        } else {
                            getDeviceList().put(mDevice.getBtaddress(), mBlueToothAdapter.getRemoteDevice(mDevice.getBtaddress()));
                            getGattlist().put(mDevice.getBtaddress(), gatt);
                            obtainHistoryTemp2();
                        }

                        ThreadUtils.runOnOtherThread(() -> {
                            while (isReadCache) {
                                int out = cacheLength;
                                SystemClock.sleep(TEMP_LOAD_TIME_DIV);
                                //  超时判断定线程
                                if (cacheLength > 0 && out == cacheLength && isReadCache) {
                                    TestManager.handleCacheTemps(mDevice.getBtaddress(), cacheData);
                                    //发送缓存超时消息
                                    EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.TEST_CACHE_TIMEOUT));

                                    isReadCache = false;
                                    cacheLength = 0;

                                    if (null == TestManager.get(mDevice.getBtaddress()) || !TestManager.get(mDevice.getBtaddress()).isTesting) {
                                        disconnectDevice(mDevice.getBtaddress());
                                        gatt.close();
                                        return;
                                    }

                                    if (isConnected && AppUtils.compareVersion(mDevice.getVersion(), "V1.0.2") >= 0) {
                                        //如果是连接状态超时，重新获取缓存数据
                                        obtainHistoryTemp();
                                        return;
                                    }

                                    EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.DEVICE_LOADED_CACHE));
                                    obtainRealTemp();
                                    //防止4.4上无法获取到设备电量
                                    obtainDevicePower();
                                }
                            }
                        });
                        return;
                    } else {
                        EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.DEVICE_LOADED_CACHE));
                        //读取完成后进行时间校准（中途体温贴关闭的情况）
                        TestManager.patchTempData(mDevice.getBtaddress());
                        TestManager.setFirstConnect(mDevice.getBtaddress(), false);
                        //获取实时数据
                        obtainRealTemp();
                        //防止4.4上无法获取到设备电量
                        obtainDevicePower();
                        LogUtils.d("DEVICE_LOADED_CACHE +++++");
                    }
                }

                if (isReadCache) {
                    String temps = BlueUtils.bytesToHexString(characteristic.getValue());
                    ThreadUtils.postCacheData(() -> {
                        for (int i = 0; i < 10; i++) {
                            if (0 < cacheLength) {
                                String temp = temps.substring(i * 4, (i + 1) * 4);
                                if (temp.equalsIgnoreCase("0000")) {
                                    continue;
                                }
                                float a = Integer.parseInt(temp.substring(2, 4) + temp.substring(0, 2), 16);
                                float b = a / 100;
                                if (AppUtils.compareVersion(mDevice.getVersion(), "1.0.2") < 0) {
                                    if (i % 2 == 0) {
                                        cacheData.add(b);
                                    }
                                } else if (AppUtils.compareVersion(mDevice.getVersion(), "1.0.2") >= 0) {
                                    //1.0.2以上版本的固件24秒缓存一个数据,需要算法补全
//                                    % x2和x1中间间隔n个点的处理方式
//                                            % 一共有n+1个间隔
//                                            del = x2-x1;
//                                    a = del/n/(n+1);
//                                    k = del/2/(n+1);
//                                    x(i)=x(i-1)+k+(n-i+1)*a;
//                                    if (null == TestManager.get(mac) || TestManager.get(mac).allTemps.size() <= 0) {
                                    float x0 = 0;
                                    float x3 = 0;

                                    if (cacheData.size() > 0) {
                                        x0 = cacheData.get(cacheData.size() - 1);
                                        x3 = b;

                                        float del = x3 - x0;
                                        float k = del / 6F;

                                        float x1 = x0 + 3F * k;
                                        float x2 = x1 + 2F * k;

                                        DecimalFormat decimalFormat = new DecimalFormat(".00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
                                        cacheData.add(Float.valueOf(decimalFormat.format(x1)));
                                        cacheData.add(Float.valueOf(decimalFormat.format(x2)));
                                        cacheData.add(Float.valueOf(decimalFormat.format(x3)));
                                    } else if (cacheData.size() <= 0) {
                                        if (TestManager.getAllTemps(mDevice.getBtaddress()).size() <= 0) {
                                            cacheData.add(b);
                                            cacheData.add(b);
                                            cacheData.add(b);
                                        } else {
                                            x0 = (float) TestManager.getAllTemps(mDevice.getBtaddress()).get(TestManager.getAllTemps(mDevice.getBtaddress()).size() - 1);
                                            x3 = b;

                                            float del = x3 - x0;
                                            float k = del / 6F;

                                            float x1 = x0 + 3F * k;
                                            float x2 = x1 + 2F * k;
                                            DecimalFormat decimalFormat = new DecimalFormat(".00");//构造方法的字符格式这里如果小数不足2位,会以0补足.
                                            cacheData.add(Float.valueOf(decimalFormat.format(x1)));
                                            cacheData.add(Float.valueOf(decimalFormat.format(x2)));
                                            cacheData.add(Float.valueOf(decimalFormat.format(x3)));

                                            LogUtils.d("x1 = " + x1 + "  x2 = " + x2 + "  x3 = " + x3);
                                        }
                                    }
                                }
                            }
                        }
                        if (AppUtils.compareVersion(mDevice.getVersion(), "1.0.2") >= 0) {
                            cacheLength -= 10;
                            LogUtils.d("Read next cache temps package!");
                            obtainHistoryTemp2();
                        } else {
                            cacheLength -= 1;
                        }

                        if (cacheLength <= 0) {
                            //保存缓存数据并且添零，校准时间
                            TestManager.patchCacheTemps(mDevice.getBtaddress(), cacheData);
                            TestManager.setFirstConnect(mDevice.getBtaddress(), false);
                            EventBus.getDefault().post(new MainEvent(mDevice.getBtaddress(), Codes.DEVICE_LOADED_CACHE));
                            LogUtils.d("Read cache temps finished!");

                            isReadCache = false;
                            cacheLength = 0;

                            obtainRealTemp();
                            //防止4.4上无法获取到设备电量
                            obtainDevicePower();
                        }
                    });
                }
                LogUtils.e(dataKV);
//                LogUtils.e("History temp  HexString = " + BlueUtils.bytesToHexString(characteristic.getValue()) + "History byte = " + new String(characteristic.getValue()));
            }
        }

        /**
         * 如果该方法被调用, 此时characteristics的返回值由设备决定. APP应当将该值与
         * 要求的值相比较, 如果两者不相等, 则APP将会做相应的操作.也就是检查发送的命令是否成功
         */
        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            mGatt = gatt;
            if (characteristic.getUuid().toString().trim().equalsIgnoreCase(CHARACTER_POWER_TEMP)) {
                // 电量通知订阅成功
                LogUtils.d("ntf ======= CHARACTER_POWER_TEMP  =  " + status);
            }
            if (characteristic.getUuid().toString().trim().equalsIgnoreCase(CHARACTER_HISTORY_TEMP)) {
                LogUtils.d("ntf ======= Begin Read History Temp Data  =  " + status);
            }

            if (mWriteQueue.isEmpty()) {
                LogUtils.i("==========BLE onCharacteristicWrite…写入… 完成");
                isWriting = false;

                //可以在此处通知页面或者做其他工作
            } else {
                LogUtils.i("==========onCharacteristicWrite…=========…写下一个");
                //如果队列中还有数据，继续写入
                isWriting = false;
                nextWrite();
            }
        }

        /**
         * 写入完Descriptor之后调用此方法 应在此检查数据是否发送完毕
         */
        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
            mGatt = gatt;
            switch (descriptor.getCharacteristic().getUuid().toString().trim()) {
                case UUIDs.CHARACTER_POWER_TEMP:
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        isNtfPower = true;
                        LogUtils.d("=================Subscriber Power NTF Succeed !=====================");
                    } else {
                        LogUtils.e("=================Subscriber Power NTF Failed !=====================");
                    }
                    break;
                case UUIDs.NTF_HISTORY_TEMP:
                    if (status == BluetoothGatt.GATT_SUCCESS) {
                        isNtfHistory = true;
                        obtainHistoryTemp();
                        LogUtils.d("=================Subscriber History Temp Data NTF Succeed !=====================");
                    } else {
                        LogUtils.e("=================Subscriber History Temp Data NTF Failed !=====================");
                    }
                    break;
                default:
                    break;
            }

            if (!isNtfHistory) {
                LogUtils.e("=================Subscriber History Temp Data NTF Failed !=====================");
                enableNotification(true, gatt, mHistoryTempNTF);
            }

            if (!isNtfPower) {
                LogUtils.e("=================Subscriber Power NTF Failed !=====================");
                enableNotification(true, gatt, mPowerNTF);
            }

            if (mWriteQueue.isEmpty()) {
                LogUtils.i("1008611" + "==========BLE onDescriptorWrite…写入… 完成");
                isWriting = false;

                //可以在此处通知页面或者做其他工作
            } else {
                LogUtils.i("1008611" + "==========BLEonDescriptorWrite…=========…写下一个");
                //如果队列中还有数据，继续写入
                isWriting = false;
                nextWrite();
            }
        }

        /**
         * 读取设备信号后的回调方法
         */
        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {

        }

        private void obtainFirmWareVersion() {
            LogUtils.i("Obtain Device FirmWare Version!" + mDevice);
            //获取设备版本号
            BleWriteData bleWriteData = new BleWriteData(firmwareVersion, CHAR_READ);
            mWriteQueue.add(bleWriteData);
            LogUtils.d("Read Device Firmware Version !");

            nextWrite();
        }

        private void obtainDeviceSn() {
            LogUtils.i("Obtain Device Sn!" + mDevice);
            if (null != mSNChar && TextUtils.isEmpty(mDevice.getSn())) {
                //获取sn
                if (TextUtils.isEmpty(mDevice.getSn())) {
                    BleWriteData bleWriteData = new BleWriteData(mSNChar, CHAR_READ);
                    mWriteQueue.add(bleWriteData);
                    LogUtils.d("Read Device SN Char !");
                }
            }

            nextWrite();
        }

        private void obtainRealTemp() {
            BleWriteData bleWriteData = new BleWriteData(mDataChar, CHAR_READ);
            mWriteQueue.add(bleWriteData);
            nextWrite();
        }


        private void obtainHistoryTemp() {
            mHistoryTempChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);

            byte[] bytes = new byte[1];
            bytes[0] = 0x01;
            LogUtils.d("bytes.length   " + bytes.length);
            mHistoryTempChar.setValue(bytes);

            BleWriteData bleWriteData = new BleWriteData(mHistoryTempChar, BleWriteData.CHAR_WRITE);
            mWriteQueue.add(bleWriteData);

            nextWrite();
        }

        private void obtainHistoryTemp2() {
            mHistoryTempChar.setWriteType(BluetoothGattCharacteristic.WRITE_TYPE_DEFAULT);
            byte[] bytes = new byte[1];
            bytes[0] = 0x02;

            mHistoryTempChar.setValue(bytes);

            BleWriteData bleWriteData = new BleWriteData(mHistoryTempChar, BleWriteData.CHAR_WRITE);
            mWriteQueue.add(bleWriteData);

            nextWrite();
        }

        private void obtainDevicePower() {
            //防止4.4上无法获取到设备电量
            BleWriteData bleWriteData = new BleWriteData(mPowerNTF, CHAR_READ);
            mWriteQueue.add(bleWriteData);
            nextWrite();
        }

        /**
         * 写入数据，方法是同步的
         */
        private synchronized void nextWrite() {
//            LogUtils.d("1008611" + " nextWrite ------ isEmpty()：" + mWriteQueue.isEmpty() + "    isWriting :" + isWriting +
//                    "      BluetoothDeviceList.containsKey " + mDevice.getBtaddress() + "   " + mBluetoothDeviceList.containsKey(mDevice.getBtaddress()));
            if (!mWriteQueue.isEmpty() && !isWriting && isConnected) {
                doWrite(mWriteQueue.poll());//从数据队列里取出数据
            }
        }

        private void doWrite(BleWriteData data) {

            if (mGatt == null || data == null) {
                return;
            }

            isWriting = true;
            latSendData = data;
            initTimeOutThread();
            switch (data.writeType) {
                case CHAR_READ:
                    mGatt.readCharacteristic((BluetoothGattCharacteristic) data.object);
                    break;
                case BleWriteData.CHAR_WRITE:
                    mGatt.writeCharacteristic((BluetoothGattCharacteristic) data.object);
                    break;
                case BleWriteData.DESCRIP_WRITE:
                    mGatt.writeDescriptor((BluetoothGattDescriptor) data.object);
                    break;
                default:
                    isWriting = false;
                    nextWrite();
                    break;
            }
        }

        private void enableNotification(boolean enable, BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            if (gatt == null || characteristic == null)
                return;

            //这一步必须要有 否则收不到通知
            gatt.setCharacteristicNotification(characteristic, enable);
            BluetoothGattDescriptor clientConfig = characteristic.getDescriptor(UUID.fromString(UUIDs.UUID_NTF_CONFIG));
            if (enable) {
                clientConfig.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
            } else {
                clientConfig.setValue(BluetoothGattDescriptor.DISABLE_NOTIFICATION_VALUE);
            }
            //准备数据
            BleWriteData bData = new BleWriteData(gatt, clientConfig, BleWriteData.DESCRIP_WRITE);
            //将数据加入队列
            mWriteQueue.add(bData);
        }

        /**
         * 开启超时判断线程
         */
        private void initTimeOutThread() {
            if (timeOutThread == null && !timeOutThread_Start) {
                timeOutThread_Start = true;
                timeOutThread = new TimeOutThread();
                timeOutThread.start();
            }
        }


//        /**
//         * 指令超时判断的线程
//         */
//        class TimeOutThread extends Thread {
//            @Override
//            public void run() {
//                while (timeOutThread_Start && isConnected) {
//                    LogUtils.w("1008611" + "设备指令超时判断的线程 ----isConnected--" + isConnected + Thread.currentThread().getId());
//                    if (isWriting && isConnected) {
//                        // 超时三秒啦 且没有在读取缓存
//                        if (timeOutNum >= 3) {
//                            // 超时3次 放弃当前这条指令 发送下一条
//                            isWriting = false;
//                            timeOutNum = 0;
//                            timeOutTime = 0;
//                            //发送超时信息
////                            sendTimeOutMessage();
//
//                            if (reSendData.writeType == BleWriteData.CHAR_READ && mWriteQueue.isEmpty()) {
//                                obtainRealTemp();
//                                LogUtils.w("1008611" + "设备指令超时判断的线程 ----超时请求实时温度--" + Thread.currentThread().getId());
//                            }
//                            nextWrite();
//                            continue;
//                        }
//
//
//                        if (isConnected &&
//                                reSendData != null &&
//                                latSendData != null &&
//                                reSendData == latSendData &&
//                                reSendData.writeType == latSendData.writeType &&
//                                Arrays.toString(reSendData.writeData).equals(Arrays.toString(latSendData.writeData))) {
//
//                            timeOutNum++;
//                            //重新发送
//                            LogUtils.w("1008611" + "设备指令超时判断的线程 ----Runing---- 重新发送");
//                            doWrite(latSendData);
//                            reSendData = latSendData;
//                        } else {
//                            LogUtils.w("1008611" + "设备指令超时判断的线程 ----Runing--" + Thread.currentThread().getId());
//                            SystemClock.sleep(Settings.TEMP_LOAD_TIME_DIV);
//                            timeOutNum = 0;
//                        }
//                    }
//                }
//                timeOutThread_Start = false;
//                LogUtils.w("1008611" + "设备指令超时判断的线程 ----Stop--" + Thread.currentThread().getId());
//            }
//        }

        class TimeOutThread extends Thread {
            @Override
            public void run() {
                while (timeOutThread_Start && isConnected) {

                    if (isWriting && isConnected) {
                        if (timeOutTime == 6) {
                            // 超时三秒啦 重发
                            if (timeOutNum == 3) {
                                // 超时3次 放弃当前这条指令 发送下一条
                                isWriting = false;
                                mWriteQueue.clear();
                                timeOutNum = 0;
                                timeOutTime = 0;
                                //发送超时信息
//                            sendTimeOutMessage();
                                nextWrite();
                                continue;
                            }
                            if (isConnected && reSendData != null && latSendData != null && reSendData.writeType == latSendData.writeType && Arrays.toString(reSendData.writeData).equals(Arrays.toString(latSendData.writeData))) {
                                timeOutNum++;
                            } else {
                                timeOutNum = 1;
                            }
                            if (latSendData != null) {
                                LogUtils.w("1008611" + "设备指令超时判断的线程 ----Retry--" + Thread.currentThread().getId());
                                doWrite(latSendData);
                                reSendData = latSendData;
                            }
                            timeOutTime = 0;
                        } else {
                            int num = 0;
                            while (isWriting && isConnected) {
                                SystemClock.sleep(10);
                                num++;
                                if (num == 50) {
                                    break;
                                }
                            }
                            timeOutTime++;
                        }
                    } else {
                        int num = 0;
                        while (!isWriting && isConnected) {
                            SystemClock.sleep(120);
                            num++;
                            if (num == 1000) {
                                break;
                            }
                        }
                        LogUtils.w("1008611" + "设备指令超时判断的线程 ----Runing--" + Thread.currentThread().getId());
                    }
                }
                timeOutThread_Start = false;
            }
        }
    }

}
